package com.up.interview.redis.redisson;

import io.netty.util.concurrent.CompleteFuture;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * @author: liuchengjun
 * @title: LockManger
 * @projectName: 海联技术中台V2.0
 * @depart 软件事业部
 * @description:
 * @date: 2025/10/20/周一 16:05 (星期一)
 * @since V2.0
 */
@Component
public class LockManger {
    @Autowired
    @Qualifier("jvmLock")
    private DistributedLock jvmLock;

    @Autowired
    @Qualifier("redissonLock")
    private DistributedLock redissonLock;
    
    public Map<String,Integer> flag = new HashMap<>();

    public void lock(LockRequest request) {
        DistributedLock lock = null;
        String lockPath = request.getLockPath();
        try {
            if (ClusterModeConfig.isClusterMode()) {
                lock = redissonLock;
            }else {
                lock = jvmLock;
            }
            lock.lock(lockPath);
            request.call();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock(lockPath);
        }
    }
    public void test(){
        Node node = new Node("node1",Type.BRANCH);
        Node node21 = new Node("node21",Type.COMMON);
        Node node22 = new Node("node22",Type.COMMON);
        Node node31 = new Node("node31",Type.COMMON);
        Node node32 = new Node("node32",Type.COMMON);
        Node node4 = new Node("node4",Type.MERGE);
        node.setChildren(Arrays.asList(node21,node22));
        node21.setChildren(Arrays.asList(node31));
        node22.setChildren(Arrays.asList(node32));
        node31.setChildren(Arrays.asList(node4));
        node32.setChildren(Arrays.asList(node4));
        flag.put(node.getInstanceId(),2);
        runNode(node);
        
    }
    
    public void runNode(Node node){
        //执行当前节点业务逻辑
        //前置处理
        node.getNodeProcess().process();
        //后置处理
        //递归结束校验
        if(node.getChildren()==null || node.getChildren().size()==0){
            return;
        }
        if(node.type==Type.BRANCH){
            node.getChildren().forEach(n->{
                CompletableFuture.runAsync(()->{
                    runNode(n);
                });
            });
        }else if(node.type==Type.COMMON){
            if(isNextMerge(node)){
                //下个节点是合并节点需要等待所有分支执行完成后方可执行
                //并发操作需要加锁，可能是多台机器执行
                LockRequest lockRequest = new LockRequest(node.getInstanceId(), new ReturnCallBack<Boolean>() {
                    @Override
                    public Boolean call() throws Exception {
                        handleMerger(node);
                        return true;
                    }
                });
                lock(lockRequest);
            }else {
                runNode(node.getChildren().get(0));
            }
        }




    }

    private void handleMerger(Node node) {
        String instanceId = node.getInstanceId();
        Integer befori = flag.get(instanceId);
        flag.put(instanceId,--befori);
        Integer afteri = flag.get(instanceId);
        if(afteri==0){
            System.out.println(node.getName()+"结束分支执行");
            runNode(node.getChildren().get(0));
        }else {
            System.out.println(node.getName()+"等待其他分支执行");
        }
    }

    public boolean isNextMerge(Node node){
        return node.children != null && node.children.size()==1 && node.children.get(0).type==Type.MERGE;
    }
    
    @Data
    public class Node{
        private String name;
        private Type type;
        private String instanceId;
        private List<Node> children;
        private NodeProcess nodeProcess;

        public Node(String name, Type type) {
            this.name = name;
            this.type = type;
            this.nodeProcess = new NodeProcess(this);
            this.instanceId = "1";
        }
    }
    public enum Type{
        COMMON,BRANCH,MERGE
    }

    @Data
    public class NodeProcess{
        private Node node;

        public NodeProcess(Node node) {
            this.node = node;
        }
        
        public void process() {
            System.out.println(node.name+":处理业务逻辑完成");
        }
    }
}
